package com.zhixiang.xaec.action.system;


import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletOutputStream;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.zhixiang.core.util.AppUtil;
import com.zhixiang.core.util.FileUtils;
import com.zhixiang.core.util.UUIDGenerator;
import com.zhixiang.core.web.action.BaseAction;
import com.zhixiang.xaec.entity.system.FileDetail;
import com.zhixiang.xaec.entity.system.Forder;
import com.zhixiang.xaec.service.system.FileDetailService;
import com.zhixiang.xaec.service.system.ForderService;


@Controller
@Scope("prototype")
public class FileUploadAction extends BaseAction
{

    private static final long serialVersionUID = 1456446294271690144L;

    @Autowired
    private FileDetailService fileDetailService;

    @Autowired
    private ForderService foderService;

    private FileDetail fileDetail;

    private List<File> file; // 上传的文件，必須這麼寫

    private List<String> fileFileName; // 文件名称，必須這麼寫

    private List<String> fileContentType; // 文件类型，必須這麼寫

    // 得到配置文件中上传文件的路径
    private String root = (String)AppUtil.getSysConfig().get("uploadDir");

    /**
     * Description:文件上传
     * 
     * @return
     * @throws Exception
     * @see
     */
    public String upload()
        throws Exception
    {
        ServletActionContext.getRequest().setCharacterEncoding("UTF-8");
        // 取得需要上传的文件数组
        List<File> files = getFile();
        // 集中向数据库插入记录
        List<FileDetail> fileDetailList = new ArrayList<FileDetail>();
        // 定义文件存放路径
        String relativePath = "";
        FileDetail file = null;
        Forder forder = null;
        if (fileDetail != null && fileDetail.getForder() != null
            && StringUtils.isNotEmpty(fileDetail.getForder().getForId().toString()))
        {
            forder = foderService.get(fileDetail.getForder().getForId());
            relativePath += foderService.getPath(fileDetail.getForder());
        }
        File dir = new File(root + relativePath);
        if (!dir.exists())
        {
            dir.mkdirs();
        }
        if (files != null && files.size() > 0)
        {
            for (int i = 0; i < files.size(); i++ )
            {
                // 向数据库文件表中插入一条记录；
                file = new FileDetail();

                // 时间戳 文件命名
                file.setRealName(FileUtils.timeStampFile(getFileFileName().get(i)));
                //
                relativePath += "/" + file.getRealName();// 还需要加上文件夹

                // 文件存放相对路径
                file.setFilePath(relativePath);

                FileOutputStream fos = new FileOutputStream(new File(root, relativePath));
                FileInputStream fis = new FileInputStream(files.get(i));
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = fis.read(buffer)) > 0)
                {
                    fos.write(buffer, 0, len);
                }
                fis.close();
                fos.close();

                // 文件名
                file.setFileName(getFileFileName().get(i).substring(0,
                    getFileFileName().get(i).lastIndexOf(".")));
                // 文件后缀
                file.setExt(FileUtils.getExtensionName(getFileFileName().get(i)));
                // 文件大小
                file.setFileSize(FileUtils.getFileSize(new File(root, relativePath).length()));
                // 文件类型
                file.setFileType(getFileContentType().get(i));
                // 上传时间
                file.setCreatetime(new Date());
                // 上传者
                file.setCreator(AppUtil.getUserName());
                // 状态
                file.setDelFlag("0");

                // 设置文件夹
                file.setForder(forder);
                // 保存
                fileDetailList.add(file);

            }
            fileDetailService.saveFileList(fileDetailList);
        }
        return SUCCESS;
    }

    /**
     * Description: 文件下载
     * 
     * @see
     * @describer 通过附件id进行附件下载，多个附件先压缩为zip然后在下载
     */
    public void download()
    {

        String fileIds = getRequest().getParameter("fileId");

        FileDetail fd = null;
        //定义下载的文件名
        String downfilename = "";
        String[] ids = null;
        //对于多附件下载时用来存放文件名称与文件绝对路径
        Map<String,String> filePath = new HashMap<String,String>();
        
        ServletOutputStream sos = null;
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        ZipOutputStream zos = null;

        if (StringUtils.isNotEmpty(fileIds))
        {
            ids = fileIds.split(",");
            
            if (ids.length == 1)//单附件下载
            {
                fd = fileDetailService.get(Long.valueOf(ids[0]));
                if (fd == null)
                {
                    return;
                }
                downfilename = fd.getFileName() + "." + fd.getExt();
            }
            else//多附件下载
            {
                for (int i = 0; i < ids.length; i++ )
                {
                    fd = fileDetailService.get(Long.valueOf(ids[i]));
                    filePath.put(fd.getFileName()+"."+fd.getExt(), root + fd.getFilePath());

                }
                //生成一个随机的文件名
                downfilename = UUIDGenerator.getUUID() + ".zip";
            }
        }
        else
        {
            return;
        }

        String agent = getRequest().getHeader("user-agent");
        try
        {
            getRequest().setCharacterEncoding("UTF-8");
            getResponse().setCharacterEncoding("UTF-8");
            if (agent.contains("Firefox"))
            {
                getResponse().addHeader(
                    "Content-Disposition",
                    "attachment;filename="
                        + new String(downfilename.getBytes("UTF-8"), "ISO-8859-1"));
            }
            else
            {
                getResponse().setHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode(downfilename, "UTF-8"));
            }
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }
        if (ids.length == 1)
        {
            // 得到文件的后缀
            String suffix = fd.getFileName().substring(fd.getFileName().lastIndexOf(".") + 1);
            // 设置响应类型
            switch (suffix)
            {
                case "zip":
                    getResponse().setContentType("application/x-zip-compressed");
                    break;
                case "rar":
                    getResponse().setContentType("application/octet-stream");
                    break;
                case "docx":
                    getResponse().setContentType("application/msword");
                    break;
                case "doc":
                    getResponse().setContentType("application/msword");
                    break;
                case "xls":
                    getResponse().setContentType("application/ms-excel ");
                    break;
                case "xlsx":
                    getResponse().setContentType("application/ms-excel ");
                    break;
                case "ppt":
                    getResponse().setContentType(" application/vnd.ms-powerpoint ");
                    break;
                case "pptx":
                    getResponse().setContentType(" application/vnd.ms-powerpoint ");
                    break;
                case "pdf":
                    getResponse().setContentType("application/pdf");
                    break;
                default:
                    getResponse().setContentType("application/x-msdownload");
                    break;
            }

            try
            {
                fis = new FileInputStream(root + fd.getFilePath());
                sos = getResponse().getOutputStream();
                byte[] arrayOfByte = new byte[1024];
                for (int i = fis.read(arrayOfByte); i > 0; i = fis.read(arrayOfByte))
                {
                    sos.write(arrayOfByte, 0, i);
                }
            }
            catch (Exception localException)
            {
                localException.printStackTrace();
            }
            finally
            {
                try
                {
                    if (fis != null)
                    {
                        fis.close();
                    }
                    if (sos != null)
                    {
                        sos.flush();
                        sos.close();
                    }
                }
                catch (IOException localIOException5)
                {
                    localIOException5.printStackTrace();
                }
            }
        }
        else
        {
            getResponse().setContentType("application/x-zip-compressed");
            try
            {
                zos = new ZipOutputStream(getResponse().getOutputStream());
                byte[] bufs = new byte[1024 * 10];
                File file = null;
                
                for (Map.Entry<String, String> entry : filePath.entrySet()) {  
                    System.out.println("key = " + entry.getKey() + " and value = " + entry.getValue());
                    // 创建ZIP实体，并添加进压缩包
                    file = new File(entry.getValue());
                    ZipEntry zipEntry = new ZipEntry(entry.getKey());
                    zos.putNextEntry(zipEntry);
                    // 读取待压缩的文件并写进压缩包里
                    fis = new FileInputStream(file);
                    bis = new BufferedInputStream(fis, 1024 * 10);
                    int read = 0;
                    while ((read = bis.read(bufs, 0, 1024 * 10)) != -1)
                    {
                        zos.write(bufs, 0, read);
                    }
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                try
                {
                    if (fis != null)
                    {
                        fis.close();
                    };
                    if (bis != null)
                    {
                        bis.close();
                    };
                    if (zos != null)
                    {
                        zos.flush();
                        zos.close();
                    }
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }

    public List<File> getFile()
    {
        return file;
    }

    public void setFile(List<File> file)
    {
        this.file = file;
    }

    public List<String> getFileFileName()
    {
        return fileFileName;
    }

    public void setFileFileName(List<String> fileFileName)
    {
        this.fileFileName = fileFileName;
    }

    public List<String> getFileContentType()
    {
        return fileContentType;
    }

    public void setFileContentType(List<String> fileContentType)
    {
        this.fileContentType = fileContentType;
    }

    public FileDetail getFileDetail()
    {
        return fileDetail;
    }

    public void setFileDetail(FileDetail fileDetail)
    {
        this.fileDetail = fileDetail;
    }

}
